// internal/planner/expression/builder.go
package expression

import (
	"NumberBase/internal/parser/ast"
	"NumberBase/internal/planner/types"
	"fmt"
)

// Builder 负责从AST构建表达式
type Builder struct {
	// 后续可能需要catalog引用
}

// NewBuilder 创建表达式构建器
func NewBuilder() *Builder {
	return &Builder{}
}

// Build 从AST节点构建表达式
func (b *Builder) Build(expr ast.Expression) (types.Expression, error) {
	switch e := expr.(type) {
	case *ast.BinaryExpression:
		return b.buildBinaryExpression(e)
	case *ast.Identifier:
		return b.buildIdentifier(e)
	case *ast.LiteralExpression:
		return b.buildLiteral(e)
	// 其他表达式类型...
	default:
		return nil, fmt.Errorf("不支持的表达式类型: %T", expr)
	}
}

// 构建二元表达式
func (b *Builder) buildBinaryExpression(expr *ast.BinaryExpression) (types.Expression, error) {
	left, err := b.Build(expr.Left)
	if err != nil {
		return nil, err
	}

	right, err := b.Build(expr.Right)
	if err != nil {
		return nil, err
	}

	op, err := convertAstOperator(expr.Operator)
	if err != nil {
		return nil, err
	}

	resultType := determineResultType(op, left.ResultType(), right.ResultType())

	return &BinaryOp{
		Left:     left,
		Right:    right,
		Op:       op,
		DataType: resultType,
	}, nil
}

// buildIdentifier converts an AST identifier to an expression
func (b *Builder) buildIdentifier(expr *ast.Identifier) (types.Expression, error) {
	// Create a column reference for the identifier
	column := &types.Column{
		Name:     expr.Value,
		Table:    "",                // This would need proper resolution with a catalog
		DataType: types.TypeUnknown, // Would be resolved with catalog
	}
	return &ColumnRef{Column: column}, nil
}

// buildLiteral converts an AST literal to an expression
func (b *Builder) buildLiteral(expr *ast.LiteralExpression) (types.Expression, error) {
	dataType := types.TypeString
	if expr.Type == ast.NUMBER {
		dataType = types.TypeFloat
	}
	return &Literal{
		Value:    expr.Value,
		DataType: dataType,
	}, nil
}

// You'll also need to implement these helper functions
func convertAstOperator(astOp ast.TokenType) (types.OpType, error) {
	switch astOp {
	case ast.EQUAL:
		return types.OpEqual, nil
	case ast.GREATER:
		return types.OpGreater, nil
	case ast.LESS:
		return types.OpLess, nil
	case ast.GREATER_EQUAL:
		return types.OpGreaterEqual, nil
	case ast.LESS_EQUAL:
		return types.OpLessEqual, nil
	case ast.NOT_EQUAL:
		return types.OpNotEqual, nil
	// Add other operators...
	default:
		return types.OpUnknown, fmt.Errorf("unsupported operator: %v", astOp)
	}
}

func determineResultType(op types.OpType, leftType, rightType types.DataType) types.DataType {
	// For comparison operators, result is boolean
	if op >= types.OpEqual && op <= types.OpGreaterEqual {
		return types.TypeBoolean
	}
	// For numeric operations, follow type promotion rules
	return leftType // Simplified for now
}
